package com.sea.data.service.impl;



import com.codecrane.core.power.service.DictDetailService;
import com.codecrane.core.util.CommonUtils;
import com.codecrane.core.util.DateUtils;
import com.codecrane.core.web.BatchImportUtils;
import com.sea.data.entity.Order;
import com.sea.data.entity.OrderDetail;
import com.sea.data.entity.SalesForecast;
import com.sea.data.mapper.SalesForecastMapper;
import com.sea.data.service.SalesForecastService;
import com.sea.operate.entity.Related;
import com.sea.operate.entity.RelatedSku;
import com.sea.operate.service.RelatedService;
import com.sea.operate.service.RelatedSkuService;
import com.sea.physical.entity.CreateDespatchSku;
import com.sea.physical.entity.StockCreateSku;
import com.sea.physical.entity.StockProduce;
import com.sea.physical.service.CreateDespatchSkuService;
import com.sea.physical.service.StockCreateSkuService;
import com.sea.physical.service.StockProduceService;
import com.sea.product.entity.Channel;
import com.sea.product.entity.Product;
import com.sea.supply.entity.Receive;
import com.sea.supply.entity.WareDistribute;
import com.sea.supply.entity.WareProduce;
import com.sea.supply.service.ReceiveService;
import com.sea.supply.service.WareDistributeService;
import com.sea.supply.service.WareProduceService;
import org.apache.ibatis.annotations.Param;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 陈鸿飞
 */
@Service
public class SalesForecastServiceImpl implements SalesForecastService {

    @Autowired
    private SalesForecastMapper salesForecastMapper;
    @Autowired
    private RelatedSkuService relatedSkuService;
    @Autowired
    private RelatedService relatedService;
    @Autowired
    private ReceiveService receiveService;
    @Autowired
    private DictDetailService dictDetailService;
    @Autowired
    private CreateDespatchSkuService createDespatchSkuService;
    @Autowired
    private StockProduceService stockProduceService;
    @Autowired
    private StockCreateSkuService stockCreateSkuService;
    @Autowired
    private WareDistributeService wareDistributeService;

    @Override
    public Integer save(SalesForecast salesForecast) {
        return salesForecastMapper.insert(salesForecast);
    }

    @Override
    public List<SalesForecast> findByCnd(SalesForecast salesForecast) {
        return salesForecastMapper.findByCnd(salesForecast);
    }

    @Override
    public void importSku(InputStream inputStream, String fileName, String userRealName) throws Exception {
        Workbook workBook = BatchImportUtils.getWorkBook(inputStream, fileName);
        List<Sheet> sheets = BatchImportUtils.getSheets(workBook);
        if (null != sheets && sheets.size() > 0) {
            Sheet sheet = sheets.get(0);
            List<SalesForecast> list = BatchImportUtils.iteratorForSalesForecast(sheet);
            if (null == list || list.size() == 0) {
                throw new Exception("请至少保存一条SKU信息！");
            } else {
//                resetSalesForecast();
                for (SalesForecast salesForecast : list) {
                    RelatedSku relatedSku=new RelatedSku();
                    relatedSku.setRelatedAsin(salesForecast.getSalesAsin());
                    relatedSku.setRelatedFnSku(salesForecast.getSalesFnsku());
                    relatedSku.setRelatedSku(salesForecast.getSalesSku());
                    RelatedSku r = relatedSkuService.findByUnique(relatedSku);
                    if(null==r){
                        throw new RuntimeException("暂未查询到Listing信息,ASIN【"+salesForecast.getSalesAsin()+"】");
                    }else{
                        salesForecast.setSalesListing(r.getRelatedListingName());
                    }
                    //获取预测的日期检测当月天数
                    String salesDate = salesForecast.getSalesDate();
                    Integer day = DateUtils.getMonthLastDay(Integer.parseInt(salesDate.substring(0, 4)), Integer.parseInt(salesDate.substring(5, 7)));

                    for(Integer i=1;i<=day;i++){
                        String str=salesDate;
                        if(i<10){
                            str=str+"-0"+i;
                        }else{
                            str=str+"-"+i;
                        }
                        SalesForecast sales=new SalesForecast();
                        sales.setSalesListing(r.getRelatedListingName());
                        sales.setSalesAsin(salesForecast.getSalesAsin());
                        sales.setSalesChannelName(salesForecast.getSalesChannelName());
                        sales.setSalesSku(salesForecast.getSalesSku());
                        sales.setSalesDate(str);
                        sales.setSalesNumber(salesForecast.getSalesNumber());
                        sales.setSalesMonth(salesDate.substring(0,7));
                        sales.setSalesFnsku(salesForecast.getSalesFnsku());
                        save(sales);
                    }
                }
            }
        }
    }


    public void getSalesProduceNumber(String salesChannelName,String salesSku) throws ParseException {
        Receive rec=new Receive();
        rec.setReceiveChannelName(salesChannelName);
        rec.setReceiveSku(salesSku);
        List<Receive> list = receiveService.findByShipped(rec);
        String code = dictDetailService.findByTypeCode(31, "2");

        int produceDay = Integer.parseInt(code);
        Date now=new Date();
        String nowDate = DateUtils.dateToString(now, "yyyy-MM-dd");
        for(Receive receive:list){
            if(!receive.getReceiveChannelName().equals(salesChannelName)){
                continue;
            }
            SalesForecast salesForecast=new SalesForecast();
            //获取交期以及设置的采购入库时间
            String orderDate = receive.getOrderDate();
            int i = DateUtils.daysBetween(nowDate, orderDate);
            //超过设置的采购入库时间
            if(i<0 && i<produceDay){
                String dateToString = DateUtils.dateToString( DateUtils.addDay(new Date(), produceDay),"yyyy-MM-dd");
                salesForecast.setSalesDate(dateToString);
            }
            //没有超过设置的采购入库时间
            if((i<0 && i>produceDay)|| i>=0){
                String dateToString = DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(orderDate), produceDay),"yyyy-MM-dd");
                salesForecast.setSalesDate(dateToString);
            }
            salesForecast.setSalesSku(receive.getReceiveSku());
            salesForecast.setSalesChannelName(receive.getReceiveChannelName());
            SalesForecast forecast = salesForecastMapper.findBySkuDateChannel(salesForecast);
            if(null!=forecast){
                forecast.setSalesProduceNumber(Double.valueOf(forecast.getSalesProduceNumber()+receive.getReceiveNumber()));
                //更新在产数量
                salesForecastMapper.update(forecast);
            }
        }
    }



    @Override
    public void getSalesPhysicalNumber(String salesDate,String salesChannelName,String salesSku) throws ParseException {
        String code = dictDetailService.findByTypeCode(31, "1");
        int physicalDay = Integer.parseInt(code);
        CreateDespatchSku sku=new CreateDespatchSku();
        sku.setCreateChannelName(salesChannelName);
        sku.setCreateSku(salesSku);
        List<CreateDespatchSku> list = createDespatchSkuService.findSalesPhysicalNumber(sku);
        if(list.size()!=0){
            for(CreateDespatchSku createDespatchSku:list){

                SalesForecast salesForecast=new SalesForecast();
                salesForecast.setSalesSku(createDespatchSku.getCreateSku());
                salesForecast.setSalesChannelName(createDespatchSku.getCreateChannelName());
                String dateToString = DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(createDespatchSku.getDespatchDate()), physicalDay),"yyyy-MM-dd");

                if(DateUtils.daysBetween(salesDate, dateToString)>0){
                    salesForecast.setSalesDate(dateToString);
                }else{
                    salesForecast.setSalesDate(DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(salesDate), 1),"yyyy-MM-dd"));
                }
                SalesForecast forecast = salesForecastMapper.findBySkuDateChannel(salesForecast);
                if(null!=forecast){
                    forecast.setSalesPhysicalNumber(Double.valueOf(forecast.getSalesPhysicalNumber()+createDespatchSku.getCreateNumber()));
                    //更新在产数量
                    salesForecastMapper.update(forecast);
                }

            }
        }
    }

    @Override
    public void getSalesStockProduceNumber(String salesChannelName,String salesSku) throws ParseException {
        String code = dictDetailService.findByTypeCode(31, "4");
        int produceDay = Integer.parseInt(code);
        StockProduce produce=new StockProduce();
        produce.setStockChannelName(salesChannelName);
        produce.setStockSku(salesSku);
        List<StockProduce> list = stockProduceService.findSalesProduceNumber(produce);
        if(list.size()>0){
            String date=DateUtils.dateToString( DateUtils.addDay(new Date(), produceDay),"yyyy-MM-dd");
            for(StockProduce stockProduce:list){
                if(!stockProduce.getStockChannelName().equals(salesChannelName)){
                    continue;
                }
                SalesForecast salesForecast=new SalesForecast();
                salesForecast.setSalesSku(stockProduce.getStockSku());
                salesForecast.setSalesChannelName(stockProduce.getStockChannelName());
                salesForecast.setSalesDate(date);
                SalesForecast forecast = salesForecastMapper.findBySkuDateChannel(salesForecast);
                if(null!=forecast){
                    forecast.setSalesStockProduceNumber(Double.valueOf(forecast.getSalesStockProduceNumber()+stockProduce.getStockNumber()));
                    //更新在产数量
                    salesForecastMapper.update(forecast);
                }
            }
        }
    }


    @Override
    public void getSalesStockPhysicalNumber(String salesChannelName,String salesSku) throws ParseException {
        StockCreateSku stock=new StockCreateSku();
        stock.setStockChannelName(salesChannelName);
        stock.setCreateSku(salesSku);
        List<StockCreateSku> list = stockCreateSkuService.findSalesPhysicalNumber(stock);
        if(list.size()>0){
            String code = dictDetailService.findByTypeCode(31, "3");
            int physicalDay = Integer.parseInt(code);
            Date now=new Date();
            String nowDate = DateUtils.dateToString(now, "yyyy-MM-dd");
            for(StockCreateSku stockCreateSku:list){
                if(!stockCreateSku.getStockChannelName().equals(salesChannelName)){
                    continue;
                }
                SalesForecast salesForecast=new SalesForecast();
                //获取交期以及设置的采购入库时间
                String orderDate = stockCreateSku.getCreateTime();
                int i = DateUtils.daysBetween(nowDate, orderDate);
                if(stockCreateSku.getCreateStatus().equals(1)){
                    if(i<=0){
                        String dateToString = DateUtils.dateToString( DateUtils.addDay(new Date(), physicalDay),"yyyy-MM-dd");
                        salesForecast.setSalesDate(dateToString);
                    }else{
                        String dateToString = DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(orderDate), physicalDay),"yyyy-MM-dd");
                        salesForecast.setSalesDate(dateToString);
                    }
                }else{
                    String dateToString = DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(orderDate), physicalDay),"yyyy-MM-dd");
                    salesForecast.setSalesDate(dateToString);
                }

                salesForecast.setSalesSku(stockCreateSku.getCreateSku());
                salesForecast.setSalesChannelName(stockCreateSku.getStockChannelName());
                SalesForecast forecast = salesForecastMapper.findBySkuDateChannel(salesForecast);
                if(null!=forecast){

                    forecast.setSalesStockPhysicalNumber(Double.valueOf(stockCreateSku.getCreateNumber()+forecast.getSalesStockPhysicalNumber()));
                    //更新在产数量
                    salesForecastMapper.update(forecast);
                }
            }
        }
    }

    @Override
    public void getWareProduceNumber(String salesChannelName,String salesDate,String salesSku) throws Exception {
        WareDistribute wareProduce=new WareDistribute();
        wareProduce.setReceiveChannelName(salesChannelName);
        wareProduce.setReceiveSku(salesSku);
        List<WareDistribute> list = wareDistributeService.findByCnd(wareProduce);
        if(null != list && list.size()>0){
            String code = dictDetailService.findByTypeCode(31, "4");
            int produceDay = Integer.parseInt(code);
            for(WareDistribute produce:list){
                SalesForecast salesForecast=new SalesForecast();
                salesForecast.setSalesSku(produce.getReceiveSku());
                salesForecast.setSalesChannelName(produce.getReceiveChannelName());
                String dateToString = DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(produce.getCreateTime()), produceDay),"yyyy-MM-dd");

                if(DateUtils.daysBetween(salesDate, dateToString)>0){
                    salesForecast.setSalesDate(dateToString);
                }else{
                    salesForecast.setSalesDate(DateUtils.dateToString(DateUtils.addDay(DateUtils.stringToDate(DateUtils.dateToString(new Date())), produceDay),"yyyy-MM-dd"));
                }
                SalesForecast forecast = salesForecastMapper.findBySkuDateChannel(salesForecast);
                if(null!=forecast){
                    forecast.setSalesProduceNumber(Double.valueOf(forecast.getSalesProduceNumber()+produce.getReceiveNumber()));
                    //更新在产数量
                    salesForecastMapper.update(forecast);
                }
            }
        }

    }

    @Override
    public List<SalesForecast> findBySalesDate() {
        return salesForecastMapper.groupBySalesDate();
    }

    @Override
    public List<Map<String, Object>> findReportByListingAsin(List<String> list,List<String> mList) {
        return salesForecastMapper.findReportByListingAsin(list,mList);
    }

    @Override
    public List<SalesForecast> findSellNumber(SalesForecast salesForecast) {
        return salesForecastMapper.findSellNumber(salesForecast);
    }

    @Override
    public Integer resetStock() {
        return salesForecastMapper.resetStock();
    }

    @Override
    public Integer resetSalesForecast() {
        return salesForecastMapper.resetSalesForecast();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importSkuStock(InputStream inputStream, String fileName, String salesChannelName, String salesDate) throws Exception {
        Workbook workBook = BatchImportUtils.getWorkBook(inputStream, fileName);
        List<Sheet> sheets = BatchImportUtils.getSheets(workBook);
        if (null != sheets && sheets.size() > 0) {
            Sheet sheet = sheets.get(0);
            List<SalesForecast> list = BatchImportUtils.iteratorForSalesForecastStock(sheet);
            if (null == list || list.size() == 0) {
                throw new Exception("请至少保存一条SKU信息！");
            } else {
//                resetStock();

                for (SalesForecast salesForecast : list) {

                    getSalesProduceNumber(salesChannelName,salesForecast.getSalesSku());
                    getSalesPhysicalNumber(salesDate,salesChannelName,salesForecast.getSalesSku());
                    getSalesStockProduceNumber(salesChannelName,salesForecast.getSalesSku());
                    getSalesStockPhysicalNumber(salesChannelName,salesForecast.getSalesSku());
                    getWareProduceNumber(salesChannelName,salesDate,salesForecast.getSalesSku());

                    salesForecast.setSalesChannelName(salesChannelName);
                    salesForecast.setSalesDate(salesDate);
                    SalesForecast sales = findBySkuDateChannel(salesForecast);
                    if (null == sales) {
                        continue;
                        //throw new RuntimeException("暂未查询到该条信息【SKU:" + salesForecast.getSalesSku() + "】");
                    }

                    sales.setSalesStock(salesForecast.getSalesStock());
                    usave(sales);
                    List<SalesForecast> sellNumberList = findSellNumber(salesForecast);
                    Double beginStock = salesForecast.getSalesStock();
                    for (Integer i = 0; i < sellNumberList.size(); i++) {
                        SalesForecast forecast = sellNumberList.get(i);
                        beginStock = beginStock - forecast.getSalesNumber() + forecast.getSalesPhysicalNumber() + forecast.getSalesProduceNumber()+ forecast.getSalesStockPhysicalNumber()+ forecast.getSalesStockProduceNumber();
                        if (beginStock <= 0) {
                            beginStock = 0.0;
                        }
                        forecast.setSalesSellNumber(beginStock);
                        usave(forecast);
                    }
                }
            }
        }
    }

    @Override
    public SalesForecast findBySkuDateChannel(SalesForecast salesForecast) {
        return salesForecastMapper.findBySkuDateChannel(salesForecast);
    }

    @Override
    public Integer usave(SalesForecast salesForecast) {
        return salesForecastMapper.update(salesForecast);
    }

    @Override
    public List<SalesForecast> groupByListing() {
        return salesForecastMapper.groupByListing();
    }

    @Override
    public List<SalesForecast> groupBySalesDate() {
        return salesForecastMapper.groupBySalesDate();
    }

    @Override
    public List<SalesForecast> groupBySalesMonth() {
        return salesForecastMapper.groupBySalesMonth();
    }

    @Override
    public Double findBySalesNumber(String beginDate, String endDate, String salesListing) {
        return salesForecastMapper.findBySalesNumber(beginDate, endDate, salesListing);
    }

    @Override
    public Integer findByProduceNumber(String beginDate, String endDate, String salesListing) {
        return salesForecastMapper.findByProduceNumber(beginDate, endDate, salesListing);
    }

    @Override
    public Integer findByPhysicalNumber(String beginDate, String endDate, String salesListing) {
        return salesForecastMapper.findByPhysicalNumber(beginDate, endDate, salesListing);
    }
}
